home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / gchess40.lha / gnuchess4.0p62 / src / checkgame.c < prev    next >
C/C++ Source or Header  |  1993-06-22  |  18KB  |  817 lines

  1. /*
  2.  * checkgame.c - check a chess.lst file for illegal moves
  3.  *
  4.  * Usage: checkgame filename
  5.  *
  6.  * Copyright (c) 1992 Free Software Foundation
  7.  *
  8.  * This file is part of GNU CHESS.
  9.  *
  10.  * GNU Chess is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2, or (at your option)
  13.  * any later version.
  14.  *
  15.  * GNU Chess is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with GNU Chess; see the file COPYING.  If not, write to
  22.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  */
  24. #include <stdio.h>
  25. #include "gnuchess.h"
  26. #ifdef MSDOS
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <time.h>
  30. #define RWA_ACC "r+b"
  31. #define WA_ACC "w+b"
  32. #else
  33. #define RWA_ACC "r+"
  34. #define WA_ACC "w+"
  35. #include <sys/param.h>
  36. #include <sys/types.h>
  37. #include <sys/times.h>
  38. #endif /* MSDOS */
  39. FILE *fd;
  40.  
  41. #define truescore 0x0001
  42. #define lowerbound 0x0002
  43. #define upperbound 0x0004
  44. #define kingcastle 0x0008
  45. #define queencastle 0x0010
  46. const short otherside[3] =
  47. {black, white, neutral};
  48.  
  49. struct GameRec GameList[512];
  50. char mvstr[4][6];
  51. long i, j;
  52. short int ep;
  53. int r, c;
  54. char line[128];
  55. char *l;
  56. short int board[64];
  57. short int color[64];
  58. short int GameCnt;
  59. int from, to;
  60. char *InPtr;
  61. int ckcastld[2];
  62. short int epsquare = -1;
  63. int ok;
  64. int mvptr = 0;
  65. struct leaf Tree[256];
  66.  
  67. /* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */
  68.  
  69. const short kingP[3] =
  70. {4, 60, 0};
  71. const short Stboard[64] =
  72. {rook, knight, bishop, queen, king, bishop, knight, rook,
  73.  pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
  74.  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  75.  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  76.  pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
  77.  rook, knight, bishop, queen, king, bishop, knight, rook};
  78. const short Stcolor[64] =
  79. {white, white, white, white, white, white, white, white,
  80.  white, white, white, white, white, white, white, white,
  81.  neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral,
  82.  neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral,
  83.  neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral,
  84.  neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral,
  85.  black, black, black, black, black, black, black, black,
  86.  black, black, black, black, black, black, black, black};
  87. short board[64], color[64];
  88.  
  89. /*
  90.  * nextpos[piece][from-square] , nextdir[piece][from-square] gives vector of
  91.  * positions reachable from from-square in ppos with piece such that the
  92.  * sequence    ppos = nextpos[piece][from-square]; pdir =
  93.  * nextdir[piece][from-square]; u = ppos[sq]; do { u = ppos[u]; if(color[u]
  94.  * != neutral) u = pdir[u]; } while (sq != u); will generate the sequence of
  95.  * all squares reachable from sq.
  96.  *
  97.  * If the path is blocked u = pdir[sq] will generate the continuation of the
  98.  * sequence in other directions.
  99.  */
  100.  
  101. unsigned char nextpos[8][64][64];
  102. unsigned char nextdir[8][64][64];
  103.  
  104. /*
  105.  * ptype is used to separate white and black pawns, like this; ptyp =
  106.  * ptype[side][piece] piece can be used directly in nextpos/nextdir when
  107.  * generating moves for pieces that are not black pawns.
  108.  */
  109. const short ptype[2][8] =
  110. {
  111.   { no_piece, pawn, knight, bishop, rook, queen, king, no_piece },
  112.   { no_piece, bpawn, knight, bishop, rook, queen, king, no_piece } };
  113.  
  114. /* data used to generate nextpos/nextdir */
  115. static const short direc[8][8] =
  116. {
  117.   { 0, 0, 0, 0, 0, 0, 0, 0 },
  118.   { 10, 9, 11, 0, 0, 0, 0, 0 },
  119.   { 8, -8, 12, -12, 19, -19, 21, -21 },
  120.   { 9, 11, -9, -11, 0, 0, 0, 0 },
  121.   { 1, 10, -1, -10, 0, 0, 0, 0 },
  122.   { 1, 10, -1, -10, 9, 11, -9, -11 },
  123.   { 1, 10, -1, -10, 9, 11, -9, -11 },
  124.   { -10, -9, -11, 0, 0, 0, 0, 0 } };
  125. static const short max_steps[8] =
  126. {0, 2, 1, 7, 7, 7, 1, 2};
  127. static const short nunmap[120] =
  128. {
  129.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  130.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  131.   -1, 0, 1, 2, 3, 4, 5, 6, 7, -1,
  132.   -1, 8, 9, 10, 11, 12, 13, 14, 15, -1,
  133.   -1, 16, 17, 18, 19, 20, 21, 22, 23, -1,
  134.   -1, 24, 25, 26, 27, 28, 29, 30, 31, -1,
  135.   -1, 32, 33, 34, 35, 36, 37, 38, 39, -1,
  136.   -1, 40, 41, 42, 43, 44, 45, 46, 47, -1,
  137.   -1, 48, 49, 50, 51, 52, 53, 54, 55, -1,
  138.   -1, 56, 57, 58, 59, 60, 61, 62, 63, -1,
  139.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  140.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
  141.  
  142. int InitFlag = false;
  143.  
  144.  
  145. void
  146. DISP (void)
  147. {
  148.  
  149.   short r, c, l;
  150.  
  151.   if (true)
  152.     {
  153.       printf ("\n");
  154.       for (r = 7; r >= 0; r--)
  155.     {
  156.       for (c = 0; c <= 7; c++)
  157.         {
  158.           l = locn (r, c);
  159.           if (color[l] == neutral)
  160.         printf (" -");
  161.           else if (color[l] == white)
  162.         printf (" %c", Qxx[board[l]]);
  163.           else
  164.         printf (" %c", Pxx[board[l]]);
  165.         }
  166.       printf ("\n");
  167.     }
  168.       printf ("\n");
  169.     }
  170. }
  171.  
  172. int
  173. castle (short int side, short int kf, short int kt, short int iop)
  174.  
  175. /* Make or Unmake a castling move. */
  176.  
  177. {
  178.   register short rf, rt, xside;
  179.  
  180.   xside = otherside[side];
  181.   if (kt > kf)
  182.     {
  183.       rf = kf + 3;
  184.       rt = kt - 1;
  185.     }
  186.   else
  187.     {
  188.       rf = kf - 4;
  189.       rt = kt + 1;
  190.     }
  191.   if (kf != kingP[side] ||
  192.       board[kf] != king ||
  193.       board[rf] != rook ||
  194.       color[kt] != neutral ||
  195.       color[rt] != neutral ||
  196.       color[kt - 1] != neutral)
  197.     return (false);
  198.   else
  199.     return (true);
  200. }
  201.  
  202. void
  203. Initialize_moves (void)
  204.  
  205. /*
  206.  * This procedure pre-calculates all moves for every piece from every square.
  207.  * This data is stored in nextpos/nextdir and used later in the move
  208.  * generation routines.
  209.  */
  210.  
  211. {
  212.   short ptyp, po, p0, d, di, s, delta;
  213.   unsigned char *ppos, *pdir;
  214.   short dest[8][8];
  215.   short steps[8];
  216.   short sorted[8];
  217.  
  218.   for (ptyp = 0; ptyp < 8; ptyp++)
  219.     for (po = 0; po < 64; po++)
  220.       for (p0 = 0; p0 < 64; p0++)
  221.     {
  222.       nextpos[ptyp][po][p0] = (unsigned char) po;
  223.       nextdir[ptyp][po][p0] = (unsigned char) po;
  224.     }
  225.   for (ptyp = 1; ptyp < 8; ptyp++)
  226.     for (po = 21; po < 99; po++)
  227.       if (nunmap[po] >= 0)
  228.     {
  229.       ppos = nextpos[ptyp][nunmap[po]];
  230.       pdir = nextdir[ptyp][nunmap[po]];
  231.       /* dest is a function of direction and steps */
  232.       for (d = 0; d < 8; d++)
  233.         {
  234.           dest[d][0] = nunmap[po];
  235.           delta = direc[ptyp][d];
  236.           if (delta != 0)
  237.         {
  238.           p0 = po;
  239.           for (s = 0; s < max_steps[ptyp]; s++)
  240.             {
  241.               p0 = p0 + delta;
  242.  
  243.               /*
  244.                * break if (off
  245.                * board) or (pawns
  246.                * only move two
  247.                * steps from home
  248.                * square)
  249.                */
  250.               if ((nunmap[p0] < 0) || (((ptyp == pawn) || (ptyp == bpawn))
  251.                            && ((s > 0) && ((d > 0) || (Stboard[nunmap[po]] != pawn)))))
  252.             break;
  253.               else
  254.             dest[d][s] = nunmap[p0];
  255.             }
  256.         }
  257.           else
  258.         s = 0;
  259.  
  260.           /*
  261.            * sort dest in number of steps order
  262.            * currently no sort is done due to
  263.            * compability with the move
  264.            * generation order in old gnu chess
  265.            */
  266.           steps[d] = s;
  267.           for (di = d; s > 0 && di > 0; di--)
  268.         if (steps[sorted[di - 1]] == 0)    /* should be: < s */
  269.           sorted[di] = sorted[di - 1];
  270.         else
  271.           break;
  272.           sorted[di] = d;
  273.         }
  274.  
  275.       /*
  276.        * update nextpos/nextdir, pawns have two
  277.        * threads (capture and no capture)
  278.        */
  279.       p0 = nunmap[po];
  280.       if (ptyp == pawn || ptyp == bpawn)
  281.         {
  282.           for (s = 0; s < steps[0]; s++)
  283.         {
  284.           ppos[p0] = (unsigned char) dest[0][s];
  285.           p0 = dest[0][s];
  286.         }
  287.           p0 = nunmap[po];
  288.           for (d = 1; d < 3; d++)
  289.         {
  290.           pdir[p0] = (unsigned char) dest[d][0];
  291.           p0 = dest[d][0];
  292.         }
  293.         }
  294.       else
  295.         {
  296.           pdir[p0] = (unsigned char) dest[sorted[0]][0];
  297.           for (d = 0; d < 8; d++)
  298.         for (s = 0; s < steps[sorted[d]]; s++)
  299.           {
  300.             ppos[p0] = (unsigned char) dest[sorted[d]][s];
  301.             p0 = dest[sorted[d]][s];
  302.             if (d < 7)
  303.               pdir[p0] = (unsigned char) dest[sorted[d + 1]][0];
  304.  
  305.             /*
  306.              * else is already
  307.              * initialized
  308.              */
  309.           }
  310.         }
  311.     }
  312. }
  313.  
  314. #define Link(from,to,flag,s) \
  315. {\
  316.    node->f = from; node->t = to;\
  317.      node->reply = 0;\
  318.        node->flags = flag;\
  319.      node->score = s;\
  320.        ++node;\
  321.          ++mvptr;\
  322.          }
  323.  
  324. inline void
  325. LinkMove (short int ply,
  326.       short int f,
  327.       short int t,
  328.       short int flag,
  329.       short int xside)
  330.  
  331. /*
  332.  * Add a move to the tree.  Assign a bonus to order the moves as follows: 1.
  333.  * Principle variation 2. Capture of last moved piece 3. Other captures
  334.  * (major pieces first) 4. Killer moves 5.
  335.  */
  336.  
  337. {
  338.   register short s;
  339.   register unsigned short mv;
  340.   register struct leaf *node;
  341.  
  342.   s = 0;
  343.   node = &Tree[mvptr];
  344.   mv = (f << 8) | t;
  345.   if (row (t) == 0 || row (t) == 7)
  346.     {
  347.       flag |= promote;
  348.       Link (f, t, flag | queen, s - 20000);
  349.       Link (f, t, flag | knight, s - 20000);
  350.       Link (f, t, flag | rook, s - 20000);
  351.       flag |= bishop;
  352.     }
  353.   else if (row (t) == 1 || row (t) == 6)
  354.     {
  355.       flag |= pwnthrt;
  356.     }
  357.   Link (f, t, flag, s - 20000);
  358. }
  359.  
  360.  
  361. void
  362. GenMoves (register short int ply, register short int sq, short int side, short int xside)
  363.  
  364. /*
  365.  * Generate moves for a piece. The moves are taken from the precalulated
  366.  * array nextpos/nextdir. If the board is free, next move is choosen from
  367.  * nextpos else from nextdir.
  368.  */
  369.  
  370. {
  371.   register short u, piece;
  372.   register unsigned char *ppos, *pdir;
  373.  
  374.   mvptr = 0;
  375.   piece = board[sq];
  376.   ppos = nextpos[ptype[side][piece]][sq];
  377.   pdir = nextdir[ptype[side][piece]][sq];
  378.   if (piece == pawn)
  379.     {
  380.       u = ppos[sq];        /* follow no captures thread */
  381.       if (color[u] == neutral)
  382.     {
  383.       LinkMove (ply, sq, u, 0, xside);
  384.       u = ppos[u];
  385.       if (color[u] == neutral)
  386.         LinkMove (ply, sq, u, 0, xside);
  387.     }
  388.       u = pdir[sq];        /* follow captures thread */
  389.       if (color[u] == xside)
  390.     LinkMove (ply, sq, u, capture, xside);
  391.       else if (u == epsquare)
  392.     LinkMove (ply, sq, u, capture | epmask, xside);
  393.       u = pdir[u];
  394.       if (color[u] == xside)
  395.     LinkMove (ply, sq, u, capture, xside);
  396.       else if (u == epsquare)
  397.     LinkMove (ply, sq, u, capture | epmask, xside);
  398.  
  399.     }
  400.   else
  401.     {
  402.       u = ppos[sq];
  403.       do
  404.     {
  405.       if (color[u] == neutral)
  406.         {
  407.           LinkMove (ply, sq, u, 0, xside);
  408.           u = ppos[u];
  409.         }
  410.       else
  411.         {
  412.           if (color[u] == xside)
  413.         LinkMove (ply, sq, u, capture, xside);
  414.           u = pdir[u];
  415.         }
  416.       } while (u != sq);
  417.     }
  418. }
  419. void
  420. skip ()
  421. {
  422.   while (*InPtr != ' ')
  423.     InPtr++;
  424.   while (*InPtr == ' ')
  425.     InPtr++;
  426. }
  427. void
  428. skipb ()
  429. {
  430.   while (*InPtr == ' ')
  431.     InPtr++;
  432. }
  433. int
  434. parser (char *f, int side, unsigned short *flags)
  435. {
  436.   int c1, r1, c2, r2;
  437.  
  438.   *flags = 0;
  439.  
  440.   if (f[4] == 'o')
  441.     if (side == black)
  442.       return 0x3C3A;
  443.     else
  444.       return 0x0402;
  445.   else if (f[0] == 'o')
  446.     if (side == black)
  447.       return 0x3C3E;
  448.     else
  449.       return 0x0406;
  450.   else
  451.     {
  452.       c1 = f[0] - 'a';
  453.       r1 = f[1] - '1';
  454.       c2 = f[2] - 'a';
  455.       r2 = f[3] - '1';
  456.       if (f[4] != ' ')
  457.     {
  458.       /* promotion */
  459.       for (i = 0; i < 7; i++)
  460.         if (f[4] == Qxx[i])
  461.           {
  462.         *flags = (unsigned short)i | promote;
  463.         break;
  464.           }
  465.     }
  466.       return (locn (r1, c1) << 8) | locn (r2, c2);
  467.     }
  468.   /* return (0); */
  469. }
  470.  
  471. void
  472. algbr (short int f, short int t, short int flag)
  473.  
  474.  
  475. /*
  476.  * Generate move strings in different formats.
  477.  */
  478.  
  479. {
  480.   int m3p;
  481.  
  482.   if (f != t)
  483.     {
  484.       /* algebraic notation */
  485.       mvstr[0][0] = Cxx[column (f)];
  486.       mvstr[0][1] = Rxx[row (f)];
  487.       mvstr[0][2] = Cxx[column (t)];
  488.       mvstr[0][3] = Rxx[row (t)];
  489.       mvstr[0][4] = mvstr[3][0] = '\0';
  490.       if (((mvstr[1][0] = Pxx[board[f]]) == 'P') || (flag & promote))
  491.     {
  492.       if (mvstr[0][0] == mvstr[0][2])    /* pawn did not eat */
  493.         {
  494.           mvstr[2][0] = mvstr[1][0] = mvstr[0][2];    /* to column */
  495.           mvstr[2][1] = mvstr[1][1] = mvstr[0][3];    /* to row */
  496.           m3p = 2;
  497.         }
  498.       else
  499.         /* pawn ate */
  500.         {
  501.           mvstr[2][0] = mvstr[1][0] = mvstr[0][0];    /* column */
  502.           mvstr[2][1] = mvstr[1][1] = mvstr[0][2];    /* to column */
  503.           mvstr[2][2] = mvstr[0][3];
  504.           m3p = 3;        /* to row */
  505.         }
  506.       if (flag & promote)
  507.         {
  508.           mvstr[0][4] = mvstr[1][2] = mvstr[2][m3p] = Qxx[flag & pmask];
  509.           mvstr[1][3] = mvstr[2][m3p + 1] = mvstr[0][5] = '\0';
  510. #ifdef CHESSTOOL
  511.           mvstr[3][0] = mvstr[0][0];    /* Allow e7e8 for
  512.                          * chesstool */
  513.           mvstr[3][1] = mvstr[0][1];
  514.           mvstr[3][2] = mvstr[0][2];
  515.           mvstr[3][3] = mvstr[0][3];
  516.           mvstr[3][4] = '\0';
  517. #endif
  518.         }
  519.       mvstr[2][m3p] = mvstr[1][2] = '\0';
  520.     }
  521.       else
  522.     /* not a pawn */
  523.     {
  524.       mvstr[2][0] = mvstr[1][0];
  525.       mvstr[2][1] = mvstr[0][1];
  526.       mvstr[2][2] = mvstr[1][1] = mvstr[0][2];    /* to column */
  527.       mvstr[2][3] = mvstr[1][2] = mvstr[0][3];    /* to row */
  528.       mvstr[2][4] = mvstr[1][3] = '\0';
  529.       strcpy (mvstr[3], mvstr[2]);
  530.       mvstr[3][1] = mvstr[0][0];
  531.       if (flag & cstlmask)
  532.         {
  533.           if (t > f)
  534.         {
  535.           strcpy (mvstr[1], "o-o");
  536.           strcpy (mvstr[2], "O-O");
  537.         }
  538.           else
  539.         {
  540.           strcpy (mvstr[1], "o-o-o");
  541.           strcpy (mvstr[2], "O-O-O");
  542.         }
  543.         }
  544.     }
  545.     }
  546.   else
  547.     mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0';
  548. }
  549.  
  550. void
  551. GetGame ()
  552. {
  553.   char fb[256];
  554.   unsigned short flags;
  555.  
  556.   fgets (fb, 256, fd);
  557.   fgets (fb, 256, fd);
  558.   while (fgets (fb, 256, fd))
  559.     {
  560.       struct GameRec *g;
  561.       int side = white;
  562.  
  563.       side = otherside[side];
  564.       if (fb[0] == '\n' || fb[0] == '\r') return;
  565.       ++GameCnt;
  566.       InPtr = fb;
  567.       skipb ();
  568.       g = &GameList[GameCnt];
  569.       g->gmove = parser (InPtr, side, &flags);
  570.       skip ();
  571.       g->score = atoi (InPtr);
  572.       skip ();
  573.       g->depth = atoi (InPtr);
  574.       skip ();
  575.       g->nodes = atol (InPtr);
  576.       skip ();
  577.       g->time = atol (InPtr);
  578.       g->flags = flags;
  579.       skip ();
  580.       ++GameCnt;
  581.       g = &GameList[GameCnt];
  582.       g->gmove = parser (InPtr, side, &flags);
  583.       skip ();
  584.       g->score = atoi (InPtr);
  585.       skip ();
  586.       g->depth = atoi (InPtr);
  587.       skip ();
  588.       g->nodes = atol (InPtr);
  589.       skip ();
  590.       g->time = atol (InPtr);
  591.       g->flags = flags;
  592.  
  593.     }
  594. }
  595. short int xside, side;
  596. int
  597. getboard (int mvno)
  598.  
  599. {
  600.   register short int f, t;
  601.   short int rf, rt;
  602.   unsigned short mv;
  603.  
  604.  
  605.   /* now update the board and hash values */
  606.  
  607.   /*
  608.    * should really check the moves as we do this, but???
  609.    */
  610.   mv = GameList[mvno].gmove;
  611.   f = mv >> 8 & 0x7F;
  612.   t = mv & 0xFF;
  613.   /* can only capture other side */
  614.   if (board[t] != no_piece)
  615.     {
  616.       if (color[t] != xside)
  617.     {
  618.       algbr (f, t, 0);
  619.       printf ("Illegal move - %d %s \n", mvno, mvstr[0]);
  620.     }
  621.     }
  622.   /* there must be a piece to move */
  623.   if (board[f] == no_piece || color[f] != side)
  624.     {
  625.       algbr (f, t, 0);
  626.       printf ("Illegal move + %d %s \n", mvno, mvstr[0]);
  627.     }
  628.   /* is it EnPassant */
  629.  
  630.  
  631.   if (board[f] == pawn && board[t] == no_piece)
  632.     {
  633.       if ((row (f) == 3 &&
  634.        row (t) == 2) || (row (f) == 4 && row (t) == 5))
  635.     {
  636.       if (column (t) != column (f))
  637.         {
  638.           ep = t + ((t > f) ? -8 : 8);
  639.           if (board[ep] == pawn && color[ep] == xside)
  640.         {
  641.           board[ep] = no_piece;
  642.           color[ep] = neutral;
  643.         }
  644.         }
  645.     }
  646.     }
  647.   board[t] = board[f];
  648.   color[t] = color[f];
  649.   color[f] = neutral;
  650.   board[f] = no_piece;
  651.   /* castle moves */
  652.   if ((mv == BLACKCASTLE) || (mv == WHITECASTLE) || (mv == LONGBLACKCASTLE) || (mv == LONGWHITECASTLE))
  653.     {
  654.  
  655.       if (t > f)
  656.     {
  657.       rf = f + 3;
  658.       rt = t - 1;
  659.     }
  660.       else
  661.     {
  662.       rf = f - 4;
  663.       rt = t + 1;
  664.     }
  665.       if ((board[t] == king && color[t] == side) && (board[rf] == rook) && (color[rf] == side))
  666.     {
  667.       board[rt] = rook;
  668.       color[rt] = side;
  669.       board[rf] = no_piece;
  670.       color[rf] = neutral;
  671.       ckcastld[side] = true;
  672.     }
  673.     }
  674.   else if (GameList[i].flags & promote)
  675.  
  676.     board[t] = GameList[i].flags & pmask;
  677. }
  678.  
  679. void
  680. main (int argc, char **argv)
  681. {
  682.   int from, to;
  683.   unsigned short int mv;
  684.   int start, end;
  685.   int ii, kf, jj;
  686.  
  687.   Initialize_moves ();
  688.   ckcastld[0] = ckcastld[1] = false;
  689.  
  690.   if (argc > 4 || argc < 2)
  691.     {
  692.       printf ("Usage: game file [start [end] ] \n");
  693.       exit (1);
  694.     }
  695.   start = end = 0;
  696.  
  697.   if (argc > 2)
  698.     start = (atoi (argv[2]) * 2) - 1;
  699.   if (argc == 4)
  700.     end = (atoi (argv[3]) * 2) - 1;
  701.   side = white;
  702.   xside = black;
  703.   for (i = 0; i < 64; i++)
  704.     {
  705.       board[i] = Stboard[i];
  706.       color[i] = Stcolor[i];
  707.     }
  708.   i = 1;
  709.   if ((fd = fopen (argv[1], RWA_ACC)) == NULL)
  710.     exit (1);
  711.   GetGame ();
  712.   if (!start || start < 1 || start > GameCnt)
  713.     start = 1;
  714.   if (!end || end > GameCnt || end < 1)
  715.     end = GameCnt;
  716.   side = white;
  717.   xside = black;
  718.   for (i = 1; i < end; i++)
  719.     {
  720.       mv = GameList[i].gmove;
  721.       from = mv >> 8 & 0x7F;
  722.       to = mv & 0x7F;
  723.       algbr (from, to, 0);
  724.       if (side)
  725.     printf ("%s\n", mvstr[0]);
  726.       else
  727.     {
  728.       printf ("%d. ", 1 + ((i - 1) / 2));
  729.       printf ("%s  ", mvstr[0]);
  730.     }
  731.  
  732.       GenMoves (0, from, side, xside);
  733.       if (!ckcastld[side] && board[from] == king && color[from] == side)
  734.     {
  735.       if (castle (side, from, from + 2, 0))
  736.         {
  737.           LinkMove (0, from, from + 2, cstlmask, xside);
  738.         }
  739.       if (castle (side, from, from - 2, 0))
  740.         {
  741.           LinkMove (0, from, from - 2, cstlmask, xside);
  742.         }
  743.     }
  744.       ok = false;
  745.       for (ii = 0; ii < mvptr; ii++)
  746.     {
  747.       if (from == Tree[ii].f && to == Tree[ii].t)
  748.         {
  749.           ok = true;
  750.           break;
  751.         }
  752.     }
  753.       if (!ok)
  754.     {
  755.       algbr (from, to, 0);
  756.       printf ("Illegal move %s\n", mvstr[0]);
  757.       for (ii = 0; ii < mvptr; ii++)
  758.         {
  759.           algbr (Tree[ii].f, Tree[ii].t, 0);
  760.           printf (" %s\n", mvstr[0]);
  761.         }
  762.       DISP ();
  763.       exit (1);
  764.     }
  765.       getboard ((int)i);
  766.       if (board[to] == pawn)
  767.     if (to - from == 16)
  768.       epsquare = from + 8;
  769.     else if (from - to == 16)
  770.       epsquare = from - 8;
  771.     else
  772.       epsquare = -1;
  773.       kf = -1;
  774.       for (ii = 0; ii < 64; ii++)
  775.     {
  776.       if ((board[ii] == king) && (color[ii] == side))
  777.         {
  778.           kf = ii;
  779.           break;
  780.         }
  781.     }
  782.       if (kf < 0)
  783.     {
  784.       printf ("Badnews: you have no king\n");
  785.       DISP ();
  786.       exit (1);
  787.     }
  788.       for (ii = 0; ii < 64; ii++)
  789.     {
  790.       if (color[ii] == xside)
  791.         {
  792.           mvptr = 0;
  793.           GenMoves (0, ii, xside, side);
  794.           for (jj = 0; jj < mvptr; jj++)
  795.         {
  796.           if (Tree[jj].t == kf)
  797.             {
  798.  
  799.               printf ("Badnews: you are in check\n");
  800.               printf ("king is at %d %d\n", row (kf), column (kf));
  801.               algbr (Tree[jj].f, Tree[jj].t, 0);
  802.               printf ("move is %s\n", mvstr[0]);
  803.               DISP ();
  804.               exit (1);
  805.             }
  806.         }
  807.         }
  808.     }
  809.       xside = side;
  810.       side = otherside[side];
  811.     }
  812.   printf ("\n\n");
  813.   printf ("Final board:\n\n");
  814.   DISP ();
  815.   exit (0);
  816. }
  817.